package com.ksm.service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFImageWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.ksm.domain.dao.TauxDao;
import com.ksm.domain.dao.document.DocumentDao;
import com.ksm.domain.dao.document.type.DocumentTypeDao;
import com.ksm.domain.entity.Document;
import com.ksm.domain.entity.DocumentType;
import com.ksm.domain.entity.Justificatif;
import com.ksm.transfer.dto.DocumentDTO;
import com.ksm.transfer.dto.DocumentFilterDTO;
import com.ksm.transfer.dto.JustificatifDTO;

@Service
public class DocumentService implements IDocumentService {

	@Autowired
	DocumentDao documentDao;

	@Autowired
	DocumentTypeDao documentTypeDao;

	@Autowired
	TauxDao tauxDao;

	@Value("${file.directory.working}")
	public String workingDirectory;

	@Value("${file.directory.store}")
	public String storeDirectory;

	private static Logger LOGGER = Logger.getLogger(DocumentService.class);
	private static final String DEFAULT_WORKING_DIR = "./file/working";
	private static final String DEFAULT_STORE_DIR = "./file/store";
	private static final SimpleDateFormat FORMAT_DATE = new SimpleDateFormat("yyyy-MM-dd");
	private static final String PDF_EXTENSION = "pdf";
	private static final String JPG_EXTENSION = "jpg";
	private static PDFImageWriter pdfImageWriter = new PDFImageWriter();

	@Transactional(readOnly = true)
	public List<DocumentDTO> findDocumentByFilter(DocumentFilterDTO filterDTO) {

		LOGGER.debug("findDocumentByFilter with " + filterDTO);

		List<Document> listeDocument = documentDao.findByFilter(getDocumentTypeByLibelle(filterDTO.getType()), filterDTO.getInterlocuteur());
		List<DocumentDTO> listDTO = new ArrayList<DocumentDTO>();
		DocumentDTO documentDTO = null;

		for (Document entity : listeDocument) {
			documentDTO = new DocumentDTO(entity.getId(), entity.getId().toString(), entity.getDocumentType().getLibelle(), entity.getDocumentType().getId(),
					entity.getDateValeur(), entity.getInterlocuteur(), entity.getMontant(), entity.getTauxTva().getId());

			for (Justificatif justificatif : entity.getJustificatifs()) {
				documentDTO.addJustificatif(new JustificatifDTO(entity.getId(), justificatif.getId(), justificatif.getName(), justificatif.getPathFile(), justificatif
						.getPathPreviewFile()));
			}

			listDTO.add(documentDTO);
		}

		return listDTO;

	}

	@Override
	@Transactional
	public DocumentDTO saveDocument(DocumentDTO documentDTO) throws Exception {
		LOGGER.debug("saveDocument " + documentDTO);

		Document document = null;
		if (documentDTO != null) {
			if (documentDTO.getId() != null && documentDTO.getId() > -1) {
				document = documentDao.findOne(documentDTO.getId());
			} else {
				document = new Document();
			}

			document.setCommentaire(documentDTO.getCommentaire());
			document.setDateValeur(documentDTO.getDate());
			document.setInterlocuteur(documentDTO.getInterlocuteur());
			document.setMontant(documentDTO.getMontant());
			document.setDocumentType(documentTypeDao.findOne(documentDTO.getTypeDocumentId()));
			document.setTauxTva(tauxDao.findOne(documentDTO.getTauxTvaId()));
			documentDao.save(document);
		}
		documentDTO.setId(document.getId());
		return documentDTO;
	}

	@Override
	@Transactional
	public JustificatifDTO saveJustificatif(JustificatifDTO jDto) throws Exception {
		Justificatif aJustificatif = null;
		if (jDto.getDocumentId() != null && jDto.getDocumentId() > -1) {
			Document document = documentDao.findOne(jDto.getDocumentId());
			if (document != null) {
				aJustificatif = new Justificatif();
				aJustificatif.setDocument(document);

				document.addJustificatif(aJustificatif);
				storeFile(document, aJustificatif, jDto.getName());
				documentDao.save(document);
			}
		}
		jDto.setId(aJustificatif.getId());
		jDto.setPathPreviewFile(aJustificatif.getPathPreviewFile());
		jDto.setName(aJustificatif.getName());
		jDto.setLocation(aJustificatif.getPathFile());
		return jDto;
	}

	private void storeFile(Document document, Justificatif justificatif, String temporaryName) throws Exception {
		try {

			String dateValeur = FORMAT_DATE.format(document.getDateValeur());
			String yearDirectory = dateValeur.substring(0, 4);
			String monthDirectory = dateValeur.substring(5, 7);

			String fromTempFileName = getWorkingDirectory() + "//" + temporaryName;
			String newFileName = dateValeur + "-" + document.getDocumentType().getLibelle() + "-" + document.getJustificatifs().size();
			String toFileName = yearDirectory + "//" + monthDirectory + "//" + newFileName;
			String toFullFileName = getStoreDirectory() + "//" + toFileName + "." + PDF_EXTENSION;

			FileUtils.forceMkdir(new File(getStoreDirectory() + "//" + yearDirectory + "//" + monthDirectory));
			FileUtils.copyFile(new File(fromTempFileName), new File(toFullFileName));
			convertPdftoJpg(toFullFileName, getStoreDirectory() + "//" + toFileName);

			justificatif.setName(newFileName + "." + PDF_EXTENSION);
			justificatif.setPathFile(toFileName + "." + PDF_EXTENSION);
			justificatif.setPathPreviewFile(toFileName + "1." + JPG_EXTENSION);

		} catch (IOException e) {
			LOGGER.error(e.getMessage());
			throw new Exception(e);
		}
	}

	@Async
	public void convertPdftoJpg(String pdfFilePath, String jpgFilePath) throws Exception {
		PDDocument document = PDDocument.load(pdfFilePath);
		boolean success = pdfImageWriter.writeImage(document, JPG_EXTENSION, "", 1, 1, jpgFilePath, BufferedImage.TYPE_INT_RGB, 600);

	}

	private DocumentType getDocumentTypeByLibelle(String libelle) {

		DocumentType documentType = null;
		if (!StringUtils.isEmpty(libelle)) {
			List<DocumentType> listeType = documentTypeDao.findByLibelle(libelle);
			if (!CollectionUtils.isEmpty(listeType)) {
				documentType = listeType.get(0);
			}
		}
		return documentType;
	}

	public String getWorkingDirectory() {
		return StringUtils.isEmpty(workingDirectory) ? DEFAULT_WORKING_DIR : workingDirectory;
	}

	public String getStoreDirectory() {
		return StringUtils.isEmpty(storeDirectory) ? DEFAULT_STORE_DIR : storeDirectory;
	}

}